# -*- coding: utf-8 -*-
"""
    XFree.core.exceptions
    ~~~~~~~~~~~~~~~~~~~~~
    文件描述：XFree核心模块抛出的异常，构成XFree所有异常的根。
    作者：xfree
    邮箱：cy_83k@qq.com
"""


class BaseXFreeError(Exception):
    """
    XFree的根异常类。
    所有自定义的异常都应该继承自这个类。
    """


class ValidationError(BaseXFreeError):
    """
    用于表示验证错误的异常类，
    例如令牌验证失败、用户注册错误等。

    :param str attribute: 验证错误适用的属性名，
        如果错误适用于多个属性或整个对象，则应设置为None。
    :param str reason: 属性、属性集合或对象无效的原因。
    """

    def __init__(self, attribute, reason):
        self.attribute = attribute  # 错误适用的属性名
        self.reason = reason        # 错误原因
        super(ValidationError, self).__init__((attribute, reason))


class StopValidation(BaseXFreeError):
    """
    从验证处理器中抛出的异常类，
    用于信号验证应该立即结束，不再进行进一步处理。

    也可以用来传达验证过程中产生的所有错误。

    :param reasons: 一个包含(attribute, reason)对的序列，
        解释对象为何无效。
    """

    def __init__(self, reasons):
        self.reasons = reasons  # 包含所有错误的列表
        super(StopValidation, self).__init__(reasons)


class PersistenceError(BaseXFreeError):
    """
    用于捕获在将模型持久化到数据库时发生的错误的异常类，
    而不是让所有问题冒泡上去。
    应该在不破坏原始异常堆栈跟踪的情况下从这些异常中抛出。

    示例::
        try:
            db.session.add(new_user)
            db.session.commit()
        except Exception:
            raise PersistenceError("无法保存用户账户")
    """


def accumulate_errors(caller, validators, throw=True):
    """
    辅助函数，用于收集由一系列验证器产生的验证错误。

    :param caller: 一个函数，它调用每个验证器。
    :param validators: 一个验证器列表。
    :param throw: 一个布尔值，指示是否在收集到错误后抛出StopValidation异常。
    :return: 收集到的错误列表。
    """

    errors = []  # 存储错误的列表

    for validator in validators:
        try:
            caller(validator)  # 尝试调用验证器
        except ValidationError as e:
            errors.append((e.attribute, e.reason))  # 收集错误

    if len(errors) and throw:
        raise StopValidation(errors)  # 如果有错误且throw为True，则抛出异常

    return errors  # 返回错误列表